package com.bytz.modules.cms.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.BooleanUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bytz.common.constant.CommonConstant;
import com.bytz.common.exception.BytzBootException;
import com.bytz.common.system.base.service.impl.AbstractCrudService;
import com.bytz.common.system.query.MPJLambdaWrapperEx;
import com.bytz.common.system.query.MPJQueryGenerator;
import com.bytz.common.util.mentity.EntityMergeInfoV2;
import com.bytz.common.util.mentity.util.MergeEntityOptions;
import com.bytz.common.util.mentity.util.MergeEntityUtil;
import com.bytz.modules.cms.product.entity.Product;
import com.bytz.modules.cms.product.entity.ProductPack;
import com.bytz.modules.cms.product.entity.ProductPackDetail;
import com.bytz.modules.cms.product.mapper.ProductPackMapper;
import com.bytz.modules.cms.product.model.ProductPackModel;
import com.bytz.modules.cms.product.service.IAdminProductPackDetailService;
import com.bytz.modules.cms.product.service.IAdminProductPackService;
import com.bytz.modules.cms.product.service.IProductPackDetailService;
import com.bytz.modules.cms.reseller.entity.Reseller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Map;

@Service
public class AdminProductPackServiceImpl extends AbstractCrudService<ProductPackMapper, ProductPack, ProductPackModel> implements IAdminProductPackService {

    @Autowired
    private IAdminProductPackDetailService productPackDetailService;

    @Autowired
    private IProductPackDetailService commonProductPackDetailService;

    @Override
    protected ProductPackModel insertSaveObject(ProductPackModel saveRo) {
        if (lambdaQuery().eq(ProductPack::getPackName, saveRo.getPackName()).exists()) {
            throw new BytzBootException("已存在同名的商品包，无法保存");
        }
        save(saveRo);
        return saveRo;
    }

    @Override
    protected ProductPackModel updateSaveObject(ProductPackModel saveRo) {
        if (lambdaQuery().eq(ProductPack::getPackName, saveRo.getPackName()).ne(ProductPack::getId, saveRo.getId()).exists()) {
            throw new BytzBootException("已存在同名的商品包，无法保存");
        }
        updateById(saveRo);
        return saveRo;
    }

    @Override
    protected ProductPackModel saveOthers(ProductPackModel saveRo) {

        if (saveRo.getDetails() == null) {
            saveRo.setDetails(new ArrayList<>());
        }
        saveRo.getDetails().forEach(detailEntity -> detailEntity.setPackId(saveRo.getId()));

        EntityMergeInfoV2<ProductPackDetail> mergeInfo = MergeEntityUtil.calculateEntityMergeInfo(
                saveRo.getDetails(),
                commonProductPackDetailService.getByPackId(saveRo.getId()),
                MergeEntityOptions.<ProductPackDetail>builder().keyExtractor(ProductPackDetail::getProductId).build()
        );
        MergeEntityUtil.doDbMerge(mergeInfo, commonProductPackDetailService);

        return saveRo;
    }

    @Override
    protected boolean deleteEntity(ProductPack entity) {
        return removeById(entity.getId());
    }

    @Override
    protected void deleteOthers(ProductPack entity) {
        productPackDetailService.removeByPackId(entity.getId());
    }

    @Override
    public IPage<ProductPackModel> queryPage(Page<ProductPack> packPage, ProductPackModel packModel, Map<String, String[]> parameterMap) throws Exception {

        Boolean resellerOnly = packModel.getResellerOnly();
        packModel.setResellerOnly(null);

        MPJLambdaWrapperEx<ProductPack> wrapper = MPJQueryGenerator.initQueryWrapper(packModel, parameterMap, ProductPack.class);

        return baseMapper.selectJoinPage(packPage, ProductPackModel.class, wrapper
                .selectAll(ProductPack.class)
                .select(Reseller::getResellerName)
                .selectCount(ProductPackDetail::getId, ProductPackModel::getProductCount)
                .selectSum(Product::getBasePrice, ProductPackModel::getPriceCount)
                .leftJoin(Reseller.class, on -> on
                        .eq(Reseller::getId, ProductPack::getResellerId)
                        .eq(Reseller::getDelFlag, CommonConstant.DEL_FLAG_0))
                .leftJoin(ProductPackDetail.class, on -> on
                        .eq(ProductPackDetail::getPackId, ProductPack::getId)
                        .eq(ProductPackDetail::getDelFlag, CommonConstant.DEL_FLAG_0)
                )
                .leftJoin(Product.class, on -> on
                        .eq(Product::getId, ProductPackDetail::getProductId)
                        .eq(Product::getDelFlag, CommonConstant.DEL_FLAG_0)
                )
                .isNull(BooleanUtil.isFalse(resellerOnly), ProductPack::getResellerId)
                .isNotNull(BooleanUtil.isTrue(resellerOnly), ProductPack::getResellerId)
                .groupBy(ProductPack::getId));
    }

    @Override
    public ProductPackModel queryById(String id) {

        ProductPack pack = getById(id);

        ProductPackModel model = BeanUtil.copyProperties(pack, ProductPackModel.class);
        model.setDetails(productPackDetailService.getByPackId(id));

        return model;
    }
}
